import sys
from PyQt4.QtCore import QDataStream, Qt, QVariant
from PyQt4.QtGui import *

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from cPickle import dumps, load, loads
from cStringIO import StringIO

class PyMimeData(QMimeData):
    """ The PyMimeData wraps a Python instance as MIME data.
    """
    # The MIME type for instances.
    MIME_TYPE = QString('text/plain')

    def __init__(self, data=None):
        """ Initialise the instance.
        """
        QMimeData.__init__(self)

        # Keep a local reference to be returned if possible.
        self._local_instance = data

        if data is not None:
            # We may not be able to pickle the data.
            try:
                pdata = dumps(data)
            except:
                return

            # This format (as opposed to using a single sequence) allows the
            # type to be extracted without unpickling the data itself.
            self.setData(self.MIME_TYPE, dumps(data.__class__) + pdata)

    @classmethod
    def coerce(cls, md):
        """ Coerce a QMimeData instance to a PyMimeData instance if possible.
        """
        # See if the data is already of the right type.  If it is then we know
        # we are in the same process.
        if isinstance(md, cls):
            return md

        # See if the data type is supported.
        if not md.hasFormat(cls.MIME_TYPE):
            return None

        nmd = cls()
        nmd.setData(cls.MIME_TYPE, md.data())

        return nmd

    def instance(self):
        """ Return the instance.
        """
        if self._local_instance is not None:
            return self._local_instance

        io = StringIO(str(self.data(self.MIME_TYPE)))

        try:
            # Skip the type.
            load(io)

            # Recreate the instance.
            return load(io)
        except:
            pass

        return None

    def instanceType(self):
        """ Return the type of the instance.
        """
        if self._local_instance is not None:
            return self._local_instance.__class__

        try:
            return loads(str(self.data(self.MIME_TYPE)))
        except:
            pass

        return None

class TreeModel(QStandardItemModel):

    def __init__(self, parent = None):

        QStandardItemModel.__init__(self, parent)
    
    def mimeTypes(self):
        
        types = QStringList()
        types.append('text/plain');
        print 'mimeTypes', types
        return types;

    def mimeData(self, index):
        item = self.itemFromIndex(index[0])
        mimeData = PyMimeData("fiejfiejif")
        return mimeData
        #return False

    def dropMimeData(self, data, action, row, column, parent):
        print 'drop', data
        self.appendRow(QStandardItem("Hello"))
        return True

    def decdode_data(self, bytearray):

        data = {}

        ds = QDataStream(bytearray)
        while not ds.atEnd():

            row = ds.readInt32()
            column = ds.readInt32()

            map_items = ds.readInt32()
            for i in range(map_items):

                key = ds.readInt32()

                value = QVariant()
                ds >> value
                data[Qt.ItemDataRole(key)] = value

        return data

app = QApplication(sys.argv)

window = QWidget()

listModel = QStringListModel(["John", "Jane", "Frank", "Henry"])
listView = QListView()
listView.setModel(listModel)
listView.setDragEnabled(True)

treeModel = TreeModel()
treeModel.appendRow(QStandardItem("Hello"))
treeModel.appendRow(QStandardItem("Huhu"))

treeView = QTreeView()
#treeView.setHeaderHidden(True)
#treeView.setRootIsDecorated(False)
treeView.setDragDropMode(QAbstractItemView.DragDrop)
treeView.setAcceptDrops(True)
treeView.setDragEnabled(True)
treeView.setModel(treeModel)

layout = QHBoxLayout(window)
layout.addWidget(listView)
layout.addWidget(treeView)

window.show()
sys.exit(app.exec_())